package nl.ViewerServer.SessionManager.Objects;

import nl.ViewerServer.Exceptions.ServerException;

public class Job {   
   public final long               jobId;
   public final transient Session  session;

   public final transient String[] inParameterNames;
   public final transient Object[] inJavaObjectParameterValues;
   public final transient String   output;

   protected Status                status;
   protected String                statusMessage = null;

   protected final long            submitTime;
   protected long                  startTime     = -1;
   protected long                  endTime       = -1;

   // this parameter is purely used for testing purposes
   protected int                   pvThreads     = 0;

   public enum Status {
      WAITING, WORKING, FINISHED, FAILED
   };

   public Job( long jobId, Session session, String output, String[] inParameterNames,
         Object[] inJavaObjectParameterValues ) {
      super();
      this.jobId = jobId;
      this.session = session;
      this.output = output;
      this.inParameterNames = inParameterNames;
      this.inJavaObjectParameterValues = inJavaObjectParameterValues;
      this.status = Status.WAITING;

      this.submitTime = System.currentTimeMillis();
   }

   public synchronized Status getStatus() {
      return status;
   }

   public void setStatus( Job.Status newStatus, String message ) {
      try {
         session.readLock.lock();

         synchronized( this ) {
            if( this.status != newStatus ) {
               this.status = newStatus;
            }
            this.statusMessage = message;

            if( newStatus == Status.WORKING ) {
               this.startTime = System.currentTimeMillis();
               this.endTime = -1;
            } else if( newStatus == Status.FAILED || newStatus == Status.FINISHED )
               this.endTime = System.currentTimeMillis();
         }
      }
      finally {
         session.readLock.unlock();
      }

   }

   public void setStatus( Job.Status newStatus ) {
      setStatus( newStatus, null );
   }

   public boolean waitForFinish( long timeoutMs ) throws ServerException {
      long timeoutTime = System.currentTimeMillis() + timeoutMs;
      while( System.currentTimeMillis() < timeoutTime ) {
         if( status == Status.FINISHED || status == Status.FAILED )
            return true;

         if( session.getStatus() == Session.Status.CLOSED || session.getStatus() == Session.Status.FAILED )
            return false;

         try {
            Thread.sleep( 1 ); // this will probably be 10-20ms average waiting per loop
         }
         catch( InterruptedException ie ) {
            // ignore
         }
      }

      return( status == Status.FINISHED || status == Status.FAILED );
   }

   public synchronized String getStatusMessage() {
      return statusMessage;
   }

   /**
    * Set the amount of ParaView threads that the job has used to complete
    * 
    * @param pvThreads
    */
   public void setPvThreads( int pvThreads ) {
      try {
         session.readLock.lock();
      
         this.pvThreads = pvThreads;
      }
      finally {
         session.readLock.unlock();
      }
   }
}
